package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.minio.MinioProperties;
import com.atguigu.lease.web.admin.service.FileService;
import io.minio.*;
import io.minio.errors.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * Package: com.atguigu.lease.web.admin.service.impl
 *
 * @Description:
 * @Author xiongkunYang
 * @Create 2025/4/27 16:08
 */
@Service
public class FileServiceImpl implements FileService {

    private final MinioClient minioClient;
    private final MinioProperties minioProperties;

    public FileServiceImpl(MinioClient minioClient, MinioProperties minioProperties) {
        this.minioClient = minioClient;
        this.minioProperties = minioProperties;
    }

    /**
     * 上传文件到MinIO服务器
     *
     * @param file 要上传的文件
     * @return 返回上传文件的URL路径
     */
    @Override
    public String upload(MultipartFile file) {
        String bucketName = minioProperties.getBucketName();
        String filename = null;
        try {
            // 检查存储桶是否存在
            boolean isBucketExists = minioClient.bucketExists(BucketExistsArgs.builder()
                    .bucket(bucketName)
                    .build());
            // 如果存储桶不存在，则创建新的存储桶并设置策略
            if (!isBucketExists) {
                minioClient.makeBucket(MakeBucketArgs.builder()
                        .bucket(bucketName)
                        .build());
                // 设置存储桶的策略配置
                minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
                        .bucket(bucketName)
                        .config(createBucketPolicyConfig(bucketName))
                        .build());
            }
            // 构造文件名，包含上传日期和唯一标识，以避免文件重复
            filename = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) +
                    "/" + UUID.randomUUID() + "-" + file.getOriginalFilename();
            // 将文件上传到MinIO服务器
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(filename)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
        } catch (ErrorResponseException e) {
            throw new LeaseException("接收到错误响应", e);
        } catch (InsufficientDataException e) {
            throw new LeaseException("提供的数据不足", e);
        } catch (InternalException e) {
            throw new LeaseException("发生内部错误", e);
        } catch (InvalidKeyException e) {
            throw new LeaseException("密钥无效", e);
        } catch (InvalidResponseException e) {
            throw new LeaseException("响应无效", e);
        } catch (IOException e) {
            throw new LeaseException("发生I/O错误", e);
        } catch (NoSuchAlgorithmException e) {
            throw new LeaseException("算法不存在", e);
        } catch (ServerException e) {
            throw new LeaseException("服务器发生错误", e);
        } catch (XmlParserException e) {
            throw new LeaseException("XML解析失败", e);
        }

        // 返回上传文件的URL路径
        return String.join("/", minioProperties.getEndpoint(), bucketName, filename);
    }

    private String createBucketPolicyConfig(String bucketName) {

        return """
                {
                  "Version" : "2012-10-17",
                  "Statement" : [ {
                    "Action" : "s3:GetObject",
                    "Effect" : "Allow",
                    "Principal" : "*",
                    "Resource" : "arn:aws:s3:::%s/*"
                  } ]
                }
                """.formatted(bucketName);
    }
}